package io.gitee.chearnee.fw.oss;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.gitee.chearnee.fw.oss.property.ALiOssProperties;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Component
@RefreshScope
public class ALiOssFileService {

  @Autowired
  ApplicationContext applicationContext;
  @Autowired
  private ALiOssProperties aLiOssProperties;
  @Autowired
  private ObjectMapper objectMapper;
  private OSS client;

  @PostConstruct
  public void initClient() {
    client = new OSSClientBuilder()
        .build(aLiOssProperties.getEndpoint(), aLiOssProperties.getAccessKeyId(),
            aLiOssProperties.getAccessKeySecret());
  }

  @PreDestroy
  public void dispose() {
    client.shutdown();
  }

  @SneakyThrows
  public String downFileToBase64Image(String baseImgUrl) {
    URL url = new URL(baseImgUrl);
    GetObjectRequest getObjectRequest = new GetObjectRequest(url, null);
    OSSObject object = client.getObject(getObjectRequest);
    if (object == null) {
      return "";
    }
    String encode = "";
    try (ByteArrayOutputStream data = new ByteArrayOutputStream()) {
      try (InputStream in = object.getObjectContent()) {
        final byte[] by = new byte[1024];
        int len = -1;
        while ((len = in.read(by)) != -1) {
          data.write(by, 0, len);
        }
      }
      Base64.Encoder encoder = Base64.getEncoder();
      //返回Base64编码过的字节数组字符串
      encode = encoder.encodeToString(data.toByteArray());
    }
    //对字节数组Base64编码
    encode = encode.replaceAll("[\s*\t\n\r]", "");
    return encode;
  }

  public String uploadBase64Image(String prefixName, String actionName, String fileName,
      String base64Image, Map<String, String> extraInfo) {
    String base64String = base64Image.replace("data:image/png;base64,", "");
    // 将base 64 转为字节数字
    byte[] buffer;
    try {
      Base64.Decoder decoder = Base64.getDecoder();
      buffer = decoder.decode(base64String);
      return uploadFile(prefixName, actionName, fileName, new ByteArrayInputStream(buffer),
              extraInfo);
    } catch (Exception ignored) {
      log.error("上传base64文件失败:{}", ignored.toString());
    }
    return null;
  }

  @SneakyThrows
  public String uploadFile(String prefixName, String actionName, String fileName,
      InputStream inputStream,
      Map<String, String> extraInfo) {
    if (!StringUtils.hasText(fileName)) {
      throw new RuntimeException("请传入文件名");
      //Asserts.failed("请传入文件名");
    }
    int extIndex = fileName.lastIndexOf(".");
    if (extIndex == fileName.length() - 1) {
      throw new RuntimeException("请传入文件的扩展名");
      //Asserts.failed("请传入文件的扩展名");
    }

    if (!client.doesBucketExist(aLiOssProperties.getDefaultBulkName())) {
      client.createBucket(aLiOssProperties.getDefaultBulkName());
    }
    StringBuilder stringBuilder = new StringBuilder(Objects
        .requireNonNull(applicationContext.getEnvironment().getProperty("spring.application.name")))
        .append("/")
        .append(aLiOssProperties.getEnv());
    if (StringUtils.hasText(prefixName)) {
      stringBuilder.append("/").append(prefixName);
    }
    stringBuilder.append("/")
        .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
    stringBuilder.append("/").append(actionName);
    stringBuilder.append("/").append(fileName, 0, extIndex).append("-")
        .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")))
        .append(fileName.substring(extIndex));
    String filePath = stringBuilder.toString();

    ObjectMetadata metadata = new ObjectMetadata();
    metadata.setContentDisposition("inline");
    // 缓存
    metadata.setCacheControl("no-store");
    if (extraInfo != null) {
      extraInfo.forEach((key, value) -> metadata.addUserMetadata("x-oss-meta-" + key, value));
    }
    PutObjectResult putObjectResult = client.putObject(
        new PutObjectRequest(aLiOssProperties.getDefaultBulkName(), filePath,
            inputStream, metadata));
    log.info("上传oss:{}", objectMapper.writeValueAsString(putObjectResult));
    return "https://" + aLiOssProperties.getDefaultBulkName() + "." + aLiOssProperties.getEndpoint()
        .substring(aLiOssProperties.getEndpoint().indexOf("//") + 2) + "/"
        + filePath;
  }
}
